using MediatR;
using ProduceBasicData.Api.Application.Command.Dashboard;
using ProduceBasicData.Api.DTO;
using ProduceBasicData.Domain.WarehouseManage;
using ProduceBasicData.ErrorCode;
using ProduceBasicData.Infrastructure.Interface;

namespace ProduceBasicData.Api.Application.Handler.Dashboard
{
    /// <summary>
    /// 获取仪表板数据处理类
    /// </summary>
    public class GetDashboardDataHandler : IRequestHandler<GetDashboardDataCommand, ApiResult<DashboardDto>>
    {
        private readonly IBaseRespository<StockInOrder> _stockInOrderRepository;
        private readonly IBaseRespository<StockOutOrder> _stockOutOrderRepository;
        private readonly IBaseRespository<StockInOrderItem> _stockInOrderItemRepository;
        private readonly IBaseRespository<StockOutOrderItem> _stockOutOrderItemRepository;

        public GetDashboardDataHandler(
            IBaseRespository<StockInOrder> stockInOrderRepository,
            IBaseRespository<StockOutOrder> stockOutOrderRepository,
            IBaseRespository<StockInOrderItem> stockInOrderItemRepository,
            IBaseRespository<StockOutOrderItem> stockOutOrderItemRepository)
        {
            _stockInOrderRepository = stockInOrderRepository;
            _stockOutOrderRepository = stockOutOrderRepository;
            _stockInOrderItemRepository = stockInOrderItemRepository;
            _stockOutOrderItemRepository = stockOutOrderItemRepository;
        }

        public async Task<ApiResult<DashboardDto>> Handle(GetDashboardDataCommand request, CancellationToken cancellationToken)
        {
            ApiResult<DashboardDto> result = new ApiResult<DashboardDto>();
            
            try
            {
                // 设置默认日期范围（本月）
                var startDate = request.StartDate ?? new DateTime(DateTime.Now.Year, DateTime.Now.Month, 1);
                var endDate = request.EndDate ?? DateTime.Now;

                var dashboardData = new DashboardDto();

                // 获取本月入库数量
                dashboardData.MonthlyInboundQuantity = await GetMonthlyInboundQuantity(startDate, endDate);

                // 获取本月出库数量
                dashboardData.MonthlyOutboundQuantity = await GetMonthlyOutboundQuantity(startDate, endDate);

                // 获取累计入库数量
                dashboardData.TotalInboundQuantity = await GetTotalInboundQuantity();

                // 获取累计出库数量
                dashboardData.TotalOutboundQuantity = await GetTotalOutboundQuantity();

                // 如果需要图表数据
                if (request.IncludeChartData)
                {
                    // 获取入库趋势数据
                    dashboardData.InboundTrend = await GetInboundTrendData(request.ChartDataDays);

                    // 获取出库趋势数据
                    dashboardData.OutboundTrend = await GetOutboundTrendData(request.ChartDataDays);

                    // 获取库存状态数据
                    dashboardData.InventoryStatus = await GetInventoryStatusData();
                }

                result.Code = ApiEnum.Success;
                result.Msg = "查询成功";
                result.Data = dashboardData;
            }
            catch (Exception ex)
            {
                result.Code = ApiEnum.Failed;
                result.Msg = $"查询失败：{ex.Message}";
                result.Data = new DashboardDto();
            }

            return result;
        }

        /// <summary>
        /// 获取本月入库数量
        /// </summary>
        private async Task<int> GetMonthlyInboundQuantity(DateTime startDate, DateTime endDate)
        {
            var stockInOrderIds = _stockInOrderRepository.GetAll()
                .Where(x => !x.Isdel && 
                           x.ActualInDate.Value >= startDate && 
                           x.ActualInDate.Value <= endDate)
                .Select(x => x.Id)
                .ToList();

            var totalQuantity = await Task.FromResult(
                _stockInOrderItemRepository.GetAll()
                    .Where(item => !item.Isdel && stockInOrderIds.Contains(item.StockInOrderId))
                    .Sum(item => (int)item.ActualQuantity)
            );

            return totalQuantity;
        }

        /// <summary>
        /// 获取本月出库数量
        /// </summary>
        private async Task<int> GetMonthlyOutboundQuantity(DateTime startDate, DateTime endDate)
        {
            // 先从出库单明细表查询存在的出库单ID
            var stockOutOrderIds = _stockOutOrderItemRepository.GetAll()
                .Where(item => !item.Isdel && item.StockOutOrderId.HasValue)
                .Select(item => item.StockOutOrderId.Value)
                .Distinct()
                .ToList();

            // 然后筛选在指定时间范围内的出库单
            var validStockOutOrderIds = _stockOutOrderRepository.GetAll()
                .Where(x => !x.Isdel && 
                           x.ExpectedOutDate.HasValue && 
                           x.ExpectedOutDate.Value >= startDate && 
                           x.ExpectedOutDate.Value <= endDate &&
                           stockOutOrderIds.Contains(x.Id))
                .Select(x => x.Id)
                .ToList();

            // 统计出库单明细表的计划数量
            var totalQuantity = await Task.FromResult(
                _stockOutOrderItemRepository.GetAll()
                    .Where(item => !item.Isdel && 
                                  item.StockOutOrderId.HasValue && 
                                  validStockOutOrderIds.Contains(item.StockOutOrderId.Value))
                    .Sum(item => (int)item.PlannedQuantity)
            );

            return totalQuantity;
        }

        /// <summary>
        /// 获取累计入库数量
        /// </summary>
        private async Task<int> GetTotalInboundQuantity()
        {
            var totalQuantity = await Task.FromResult(
                _stockInOrderItemRepository.GetAll()
                    .Where(item => !item.Isdel)
                    .Sum(item => (int)item.ActualQuantity)
            );

            return totalQuantity;
        }

        /// <summary>
        /// 获取累计出库数量
        /// </summary>
        private async Task<int> GetTotalOutboundQuantity()
        {
            // 先从出库单明细表查询存在的出库单ID
            var stockOutOrderIds = _stockOutOrderItemRepository.GetAll()
                .Where(item => !item.Isdel && item.StockOutOrderId.HasValue)
                .Select(item => item.StockOutOrderId.Value)
                .Distinct()
                .ToList();

            // 筛选有效的出库单（已出库的）
            var validStockOutOrderIds = _stockOutOrderRepository.GetAll()
                .Where(x => !x.Isdel && 
                           x.ExpectedOutDate.HasValue &&
                           stockOutOrderIds.Contains(x.Id))
                .Select(x => x.Id)
                .ToList();

            // 统计出库单明细表的计划数量
            var totalQuantity = await Task.FromResult(
                _stockOutOrderItemRepository.GetAll()
                    .Where(item => !item.Isdel && 
                                  item.StockOutOrderId.HasValue && 
                                  validStockOutOrderIds.Contains(item.StockOutOrderId.Value))
                    .Sum(item => (int)item.PlannedQuantity)
            );

            return totalQuantity;
        }

        /// <summary>
        /// 获取入库趋势数据
        /// </summary>
        private async Task<List<ChartDataPoint>> GetInboundTrendData(int days)
        {
            var endDate = DateTime.Now.Date; // 使用Date确保只比较日期部分
            var startDate = endDate.AddDays(-days + 1).Date; // 确保开始日期也是日期部分

            var trendData = new List<ChartDataPoint>();

            for (int i = 0; i < days; i++)
            {
                var currentDate = startDate.AddDays(i);
                var nextDate = currentDate.AddDays(1);

                // 使用日期范围查询，确保精确匹配
                var stockInOrderIds = _stockInOrderRepository.GetAll()
                    .Where(x => !x.Isdel && 
                               x.ActualInDate.HasValue &&
                               x.ActualInDate.Value.Date >= currentDate && // 使用.Date确保只比较日期
                               x.ActualInDate.Value.Date < nextDate)      // 使用.Date确保只比较日期
                    .Select(x => x.Id)
                    .ToList();

                var dailyQuantity = _stockInOrderItemRepository.GetAll()
                    .Where(item => !item.Isdel && stockInOrderIds.Contains(item.StockInOrderId))
                    .Sum(item => (int)item.ActualQuantity);

                trendData.Add(new ChartDataPoint
                {
                    Name = currentDate.ToString("MM-dd"),
                    Value = dailyQuantity,
                    Date = currentDate
                });
            }

            return await Task.FromResult(trendData);
        }

        /// <summary>
        /// 获取出库趋势数据
        /// </summary>
        private async Task<List<ChartDataPoint>> GetOutboundTrendData(int days)
        {
            var endDate = DateTime.Now.Date; // 使用Date确保只比较日期部分
            var startDate = endDate.AddDays(-days + 1).Date; // 确保开始日期也是日期部分

            var trendData = new List<ChartDataPoint>();

            for (int i = 0; i < days; i++)
            {
                var currentDate = startDate.AddDays(i);
                var nextDate = currentDate.AddDays(1);

                // 先从出库单明细表查询存在的出库单ID
                var allStockOutOrderIds = _stockOutOrderItemRepository.GetAll()
                    .Where(item => !item.Isdel && item.StockOutOrderId.HasValue)
                    .Select(item => item.StockOutOrderId.Value)
                    .Distinct()
                    .ToList();

                // 然后筛选在指定日期范围内的出库单
                var stockOutOrderIds = _stockOutOrderRepository.GetAll()
                    .Where(x => !x.Isdel && 
                               x.ActualOutDate.HasValue &&
                               x.ActualOutDate.Value.Date >= currentDate && // 使用.Date确保只比较日期
                               x.ActualOutDate.Value.Date < nextDate &&      // 使用.Date确保只比较日期
                               allStockOutOrderIds.Contains(x.Id))
                    .Select(x => x.Id)
                    .ToList(); 

                var dailyQuantity = _stockOutOrderItemRepository.GetAll()
                    .Where(item => !item.Isdel && 
                                  item.StockOutOrderId.HasValue && 
                                  stockOutOrderIds.Contains(item.StockOutOrderId.Value))
                    .Sum(item => (int)item.PlannedQuantity);

                trendData.Add(new ChartDataPoint
                {
                    Name = currentDate.ToString("MM-dd"),
                    Value = dailyQuantity,
                    Date = currentDate
                });
            }

            return await Task.FromResult(trendData);
        }

        /// <summary>
        /// 获取库存状态数据
        /// </summary>
        private async Task<List<ChartDataPoint>> GetInventoryStatusData()
        {
            // 获取所有入库数量
            var totalInbound = _stockInOrderItemRepository.GetAll()
                .Where(item => !item.Isdel)
                .Sum(item => (int)item.ActualQuantity);

            // 先从出库单明细表查询存在的出库单ID
            var stockOutOrderIds = _stockOutOrderItemRepository.GetAll()
                .Where(item => !item.Isdel && item.StockOutOrderId.HasValue)
                .Select(item => item.StockOutOrderId.Value)
                .Distinct()
                .ToList();

            // 筛选有效的出库单（已出库的）
            var validStockOutOrderIds = _stockOutOrderRepository.GetAll()
                .Where(x => !x.Isdel && 
                           x.ActualOutDate.HasValue &&
                           stockOutOrderIds.Contains(x.Id))
                .Select(x => x.Id)
                .ToList();

            // 获取所有出库数量
            var totalOutbound = _stockOutOrderItemRepository.GetAll()
                .Where(item => !item.Isdel && 
                              item.StockOutOrderId.HasValue && 
                              validStockOutOrderIds.Contains(item.StockOutOrderId.Value))
                .Sum(item => (int)item.PlannedQuantity);

            // 计算当前库存
            var currentStock = totalInbound - totalOutbound;

            // 根据库存水平分类
            var statusData = new List<ChartDataPoint>();

            if (currentStock > 0)
            {
                if (currentStock > 10000)
                {
                    statusData.Add(new ChartDataPoint { Name = "正常库存", Value = currentStock });
                }
                else if (currentStock > 1000)
                {
                    statusData.Add(new ChartDataPoint { Name = "低库存", Value = currentStock });
                }
                else
                {
                    statusData.Add(new ChartDataPoint { Name = "极低库存", Value = currentStock });
                }
            }
            else
            {
                statusData.Add(new ChartDataPoint { Name = "零库存", Value = 0 });
            }

            // 添加历史数据统计
            statusData.Add(new ChartDataPoint { Name = "累计入库", Value = totalInbound });
            statusData.Add(new ChartDataPoint { Name = "累计出库", Value = totalOutbound });

            return await Task.FromResult(statusData);
        }
    }
}
